home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / ohlcpio.zip / COPYPASS.C < prev    next >
C/C++ Source or Header  |  1990-07-02  |  9KB  |  295 lines

  1. /* copypass.c - cpio copy pass sub-function.
  2.    Copyright (C) 1988, 1989, 1990 Free Software Foundation, Inc.
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 1, or (at your option)
  7.    any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. #include <stdio.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #ifndef S_IFLNK
  22. #define lstat stat
  23. #endif
  24. #include <errno.h>
  25. extern int errno;
  26. #include <fcntl.h>
  27. #include <sys/file.h>
  28. #ifdef USG
  29. #include <time.h>
  30. #include <string.h>
  31. #else
  32. #include <sys/time.h>
  33. #include <strings.h>
  34. #endif
  35. #include "cpio.h"
  36. #include "dstring.h"
  37. #include "extern.h"
  38.  
  39. /* Copy files listed on the standard input into directory `directory_name'.
  40.    If `link_flag', link instead of copying. */
  41.  
  42. void
  43. process_copy_pass ()
  44. {
  45.   dynamic_string input_name;    /* Name of file from stdin. */
  46.   dynamic_string output_name;    /* Name of new file. */
  47.   int dirname_len;        /* Length of `directory_name'. */
  48.   int res;            /* Result of functions. */
  49.   char *slash;            /* For moving past slashes in input name. */
  50.   long times[2];        /* For resetting file times after copy.  */
  51.   struct stat in_file_stat;    /* Stat record for input file. */
  52.   struct stat out_file_stat;    /* Stat record for output file. */
  53.   int in_file_des;        /* Input file descriptor. */
  54.   int out_file_des;        /* Output file descriptor. */
  55.  
  56.   /* Initialize the copy out. */
  57.   dirname_len = strlen (directory_name);
  58.   ds_init (&input_name, 128);
  59.   ds_init (&output_name, dirname_len + 2);
  60.   strcpy (output_name.ds_string, directory_name);
  61.   output_name.ds_string[dirname_len] = '/';
  62.   output_is_seekable = TRUE;
  63.  
  64.   /* Copy files with names read from stdin. */
  65.   while (ds_fgets (stdin, &input_name) != NULL)
  66.     {
  67.       char *link_name = NULL;
  68.  
  69.       /* Check for blank line and ignore it if found. */
  70.       if (input_name.ds_string[0] == '\0')
  71.     {
  72.       error (0, 0, "blank line ignored");
  73.       continue;
  74.     }
  75.  
  76.       if ((*xstat) (input_name.ds_string, &in_file_stat) < 0)
  77.     {
  78.       error (0, errno, "%s", input_name.ds_string);
  79.       continue;
  80.     }
  81.  
  82.       /* Make the name of the new file. */
  83.       for (slash = input_name.ds_string; *slash == '/'; ++slash)
  84.     ;
  85.       ds_resize (&output_name, dirname_len + strlen (slash) + 2);
  86.       strcpy (output_name.ds_string + dirname_len + 1, slash);
  87.  
  88.       if (lstat (output_name.ds_string, &out_file_stat) == 0)
  89.     {
  90.       if (!unconditional_flag
  91.           && in_file_stat.st_mtime < out_file_stat.st_mtime)
  92.         {
  93.           error (0, 0, "%s not created: newer version exists",
  94.              output_name.ds_string);
  95.           continue;        /* Go to the next file. */
  96.         }
  97.       else if ((out_file_stat.st_mode & S_IFMT) == S_IFDIR)
  98.         {
  99.           error (0, 0, "cannot remove current %s: Is a directory",
  100.              output_name.ds_string);
  101.           continue;        /* Go to the next file. */
  102.         }
  103.       else if (unlink (output_name.ds_string))
  104.         {
  105.           error (0, errno, "cannot remove current %s",
  106.              output_name.ds_string);
  107.           continue;        /* Go to the next file. */
  108.         }          
  109.     }
  110.  
  111.       /* Do the real copy or link.  */
  112.       switch (in_file_stat.st_mode & S_IFMT)
  113.     {
  114.     case S_IFREG:
  115.       /* Can the current file be linked to a another file?
  116.          Set link_name to the original file name.  */
  117.       if (link_flag)
  118.         {
  119.           /* User said to link it if possible. */
  120.           link_name = input_name.ds_string;
  121.         }
  122.       else if (in_file_stat.st_nlink > 1)
  123.         {
  124.           /* Is the file a link to a previously copied file?  */
  125.           link_name = find_inode_file (in_file_stat.st_ino);
  126.           if (link_name == NULL)
  127.         add_inode (in_file_stat.st_ino, output_name.ds_string);
  128.         }
  129.  
  130.       /* If there is a link name, do the link.  */
  131.       if (link_name != NULL)
  132.         {
  133.           res = link (link_name, output_name.ds_string);
  134.           if (res < 0 && create_dir_flag)
  135.         {
  136.           create_all_directories (output_name.ds_string);
  137.           res = link (link_name, output_name.ds_string);
  138.         }
  139.           if (res == 0)
  140.         {
  141.           if (verbose_flag)
  142.             error (0, 0, "%s linked to %s",
  143.                link_name, output_name.ds_string);
  144.         }
  145.           else if (link_flag)
  146.         {
  147.           error (0, errno, "cannot link %s to %s",
  148.              link_name, output_name.ds_string);
  149.         }
  150.           else
  151.         {
  152.           /* For some reason we can not link a previously linked file.
  153.              Do a complete copy. */
  154.           link_name = NULL;
  155.         }
  156.         }
  157.  
  158.       /* If the file was not linked, copy contents of file. */
  159.       if (link_name == NULL)
  160.         {
  161.           in_file_des = open (input_name.ds_string, O_RDONLY, 0);
  162.           if (in_file_des < 0)
  163.         {
  164.           error (0, errno, "%s", input_name.ds_string);
  165.           continue;
  166.         }
  167.           out_file_des = open (output_name.ds_string,
  168.                    O_CREAT | O_WRONLY, 0600);
  169.           if (out_file_des < 0 && create_dir_flag)
  170.         {
  171.           create_all_directories (output_name.ds_string);
  172.           out_file_des = open (output_name.ds_string,
  173.                        O_CREAT | O_WRONLY, 0600);
  174.         }
  175.           if (out_file_des < 0)
  176.         {
  177.           error (0, errno, "%s", output_name.ds_string);
  178.           close (in_file_des);
  179.           continue;
  180.         }
  181.  
  182.           copy_files (in_file_des, out_file_des, in_file_stat.st_size);
  183.           empty_output_buffer (out_file_des);
  184.           finish_output_file (output_name.ds_string, out_file_des);
  185.           close (in_file_des);
  186.           close (out_file_des);
  187.  
  188.           /* Set the attributes of the new file.  */
  189.           if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
  190.         error (0, errno, "%s", output_name.ds_string);
  191.           if (chown (output_name.ds_string, in_file_stat.st_uid,
  192.              in_file_stat.st_gid) < 0
  193.           && errno != EPERM)
  194.         error (0, errno, "%s", output_name.ds_string);
  195.           if (reset_time_flag)
  196.         {
  197.           times[0] = in_file_stat.st_atime;
  198.           times[1] = in_file_stat.st_mtime;
  199.           if (utime (input_name.ds_string, times) < 0)
  200.             error (0, errno, "%s", input_name.ds_string);
  201.           if (utime (output_name.ds_string, times) < 0)
  202.             error (0, errno, "%s", output_name.ds_string);
  203.         }
  204.         }
  205.       break;
  206.  
  207.     case S_IFDIR:
  208.       res = mkdir (output_name.ds_string, in_file_stat.st_mode);
  209.       if (res < 0 && create_dir_flag)
  210.         {
  211.           create_all_directories (output_name.ds_string);
  212.           res = mkdir (output_name.ds_string, in_file_stat.st_mode);
  213.         }
  214.       if (res < 0)
  215.         {
  216.           error (0, errno, "%s", output_name.ds_string);
  217.           continue;
  218.         }
  219.       if (chown (output_name.ds_string, in_file_stat.st_uid,
  220.              in_file_stat.st_gid) < 0
  221.           && errno != EPERM)
  222.         error (0, errno, "%s", output_name.ds_string);
  223.       break;
  224.  
  225.     case S_IFCHR:
  226.     case S_IFBLK:
  227. #ifdef S_IFIFO
  228.     case S_IFIFO:
  229. #endif
  230. #ifdef S_IFSOCK
  231.     case S_IFSOCK:
  232. #endif
  233.        res = mknod (output_name.ds_string, in_file_stat.st_mode,
  234.                in_file_stat.st_rdev);
  235.       if (res < 0 && create_dir_flag)
  236.         {
  237.           create_all_directories (output_name.ds_string);
  238.           res = mknod (output_name.ds_string, in_file_stat.st_mode,
  239.                in_file_stat.st_rdev);
  240.         }
  241.       if (res < 0)
  242.         {
  243.           error (0, errno, "%s", output_name.ds_string);
  244.           continue;
  245.         }
  246.       if (chown (output_name.ds_string, in_file_stat.st_uid,
  247.              in_file_stat.st_gid) < 0
  248.           && errno != EPERM)
  249.         error (0, errno, "%s", output_name.ds_string);
  250.       break;
  251.  
  252. #ifdef S_IFLNK
  253.     case S_IFLNK:
  254.       link_name = (char *) xmalloc (in_file_stat.st_size + 1);
  255.  
  256.       if (readlink (input_name.ds_string, link_name,
  257.             in_file_stat.st_size) < 0)
  258.         {
  259.           error (0, errno, "%s", input_name.ds_string);
  260.           free (link_name);
  261.           continue;
  262.         }
  263.       link_name[in_file_stat.st_size] = '\0';
  264.  
  265.       res = symlink (link_name, output_name.ds_string);
  266.       if (res < 0 && create_dir_flag)
  267.         {
  268.           create_all_directories (output_name.ds_string);
  269.           res = symlink (link_name, output_name.ds_string);
  270.         }
  271.       if (res < 0)
  272.         {
  273.           error (0, errno, "%s", output_name.ds_string);
  274.           free (link_name);
  275.           continue;
  276.         }
  277.       free (link_name);
  278.       break;
  279. #endif
  280.  
  281.     default:
  282.       error (0, 0, "%s: unknown file type", input_name.ds_string);
  283.     }
  284.  
  285.       if (verbose_flag)
  286.     fprintf (stderr, "%s\n", output_name.ds_string);
  287.     }
  288.  
  289.   res = output_bytes / io_block_size;
  290.   if (res == 1)
  291.     fprintf (stderr, "1 block\n");
  292.   else
  293.     fprintf (stderr, "%d blocks\n", res);
  294. }
  295.